﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Threading;
using System.Threading.Tasks;

namespace ApplicationLOLS13
{
    public partial class FormLOL_S13 : Form
    {
        //比赛次数
        private static int matchCount = 8;
        //晋级列表
        private static List<Team> WinTeamList = new List<Team>();
        //淘汰列表
        private static List<Team> FailTeamList = new List<Team>();
        //战队积分
        private static Dictionary<Team, int> DictPoint = new Dictionary<Team, int>();
        public FormLOL_S13()
        {
            InitializeComponent();
            rtxtDisplay.ReadOnly = true;
            rtxtDisplay.Text = @"英雄联盟全球总决赛S13比赛规则采用瑞士轮：
瑞士轮赛制的由来
瑞士制：又称积分循环制，最早出现于1895年在瑞士苏黎世举办的国际象棋比赛中，故而得名。
其基本原则是避免种子选手一开始就交锋、拼掉，是比较科学合理、用得最多的一种赛制；英语名称为Swiss System。
欲通过瑞士轮的考验进入淘汰赛，那么需要在此阶段拿下三场胜利，反之遭遇三场失利就会被淘汰。
瑞士轮阶段的比赛，包含了五个轮次的比赛，每轮的比赛对阵都由抽签来决定。
第一轮有8场比赛：比赛全部为BO1（同赛区规避），这8场比赛结束之后，16支队伍会按照胜负情况分为两组，1-0战绩的队伍8支，0-1战绩的队伍8支。
第二轮同样也是8场BO1的比赛：抽签后的对阵原则是1-0战绩的队伍和1-0战绩的队伍打（也就是第一轮的胜者打胜者），0-1战绩的队伍和0-1战绩的队伍打（也就是第一轮的败者打败者）。
此轮比赛结束后，会有4支2-0的队伍，4支0-2的队伍，8支1-1的队伍。
第三轮的比赛就显得复杂一些了，因为第三轮就会诞生率先晋级淘汰赛以及不得不遗憾出局的队伍了：关乎淘汰和晋级的比赛都将是BO3的设定，2-0的队伍打2场BO3， 1-1的队伍打4场BO1，0-2的队伍打2场BO3。
第三轮比赛结束之后，会宣告2支队伍以3-0的成绩晋级淘汰赛，2支队伍以0-3的成绩遗憾出局。
第四轮的比赛最为残酷：2-1的队伍打3场BO3，胜者晋级淘汰赛，1-2的队伍打3场BO3。比赛结束后晋级3支队伍，淘汰3支队伍；留在场上的6支队伍是全部都会是2-2的胜负场情形。
第五轮的比赛是晋级淘汰赛的最后机会，2-2的队伍们打3场BO3，晋级3支队伍淘汰3支队伍。
综上所述：通过五个轮次的比赛，8支队伍得以晋级，8支队伍遭遇淘汰。
决出八强后，直接进入淘汰赛，决出四强
四强抽签两两比赛，决出胜者组，败者组。败者组决出季军，胜者组决出冠军、亚军";
        }
        private void FormTeam_Load(object sender, EventArgs e)
        {
            TeamUtil.InitTeam();
            DictPoint.Clear();
            for (int i = 0; i < TeamUtil.ListTeam.Count; i++)
            {
                DictPoint.Add(TeamUtil.ListTeam[i], 0);
            }
            LoadMatchTeam(TeamUtil.ListTeam);
        }

        /// <summary>
        /// 随机分配参赛战队列表
        /// </summary>
        /// <param name="TeamList"></param>
        private void LoadMatchTeam(List<Team> TeamList)
        {
            panel1.Controls.Clear();
            DisplayMessage($"开始加载S13英雄联盟参赛战队.参赛战队[{TeamList.Count}]个.参赛战队：\n{string.Join(",", TeamList.Select(c => c.TeamName))}");
            Application.DoEvents();
            //Thread.Sleep(500);
            int[] indexArray = new int[TeamList.Count];
            for (int i = 0; i < indexArray.Length; i++)
            {
                indexArray[i] = i;
            }
            RandomUtil.Init(indexArray);
            int[] destArray = RandomUtil.Shuffle();
            int rowCount = (destArray.Length + 1) / 2;
            matchCount = rowCount;
            string[] matchTeams = new string[rowCount];//比赛对战战队
            for (int i = 0; i < rowCount; i++)
            {
                UcTeam ucTeam1 = new UcTeam();
                ucTeam1.Name = $"ucTeam{i * 2 + 1}";
                Team Team1 = TeamList[destArray[i * 2]];
                ucTeam1.lblTeamName.Text = Team1.TeamName;
                ucTeam1.lblWinningRatio.Text = $"胜率:{Team1.WinningRatio}";
                ucTeam1.picTeamFlag.BackgroundImage = Team1.TeamFlag;
                ucTeam1.Tag = Team1;
                ucTeam1.Location = new Point(5, i * 200 + 5);
                panel1.Controls.Add(ucTeam1);

                Button button = new Button();
                button.Name = $"button{i + 1}";
                button.Text = "VS";
                button.Font = new Font("宋体", 30, FontStyle.Bold);
                button.Size = new Size(100, 100);
                button.Location = new Point(310, i * 200 + 40);
                button.Enabled = false;//不允许界面交互
                panel1.Controls.Add(button);

                Team item2 = null;
                if (i * 2 + 1 < destArray.Length)
                {
                    //对奇数个比赛战队特殊处理，最后一个战队直接胜利
                    UcTeam ucTeam2 = new UcTeam();
                    ucTeam2.Name = $"ucTeam{i * 2 + 2}";
                    Team Team2 = TeamList[destArray[i * 2 + 1]];
                    ucTeam2.lblTeamName.Text = Team2.TeamName;
                    ucTeam2.lblWinningRatio.Text = $"胜率:{Team2.WinningRatio}";
                    ucTeam2.picTeamFlag.BackgroundImage = Team2.TeamFlag;
                    ucTeam2.Tag = Team2;
                    ucTeam2.Location = new Point(455, i * 200 + 5);
                    panel1.Controls.Add(ucTeam2);

                    item2 = Team2;
                }
                //对按钮进行数据绑定 对应两个参赛战队
                button.Tag = Tuple.Create(Team1, item2);
                button.Click += Button_Click;

                matchTeams[i] = $"【{Team1.TeamName} VS {(item2 == null ? "无" : item2.TeamName)}】";
            }
            DisplayMessage($"加载对战战队匹配完成.对战情况\n{string.Join(",\n", matchTeams)}");
        }

        /// <summary>
        /// 淘汰赛，利用胜率获取随机数算法，获取比赛的胜利一方，并将获胜战队插入胜利列表，以便进行下一次的随机分配
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_Click(object sender, EventArgs e)
        {
            Button button = sender as Button;
            if (button == null)
            {
                return;
            }
            Tuple<Team, Team> tuple = button.Tag as Tuple<Team, Team>;
            if (tuple == null)
            {
                return;
            }
            int randomNumber;
            Team failTeam;
            Team winTeam = TeamUtil.SoccerGame(tuple, out failTeam, out randomNumber);
            WinTeamList.Add(winTeam);//将获胜战队插入列表
            FailTeamList.Add(failTeam);//失败战队
            DictPoint[winTeam] = DictPoint[winTeam] + 1;
            DisplayMessage($"参赛战队【{tuple.Item1.TeamName},胜率:{tuple.Item1.WinningRatio}】 VS 【{(tuple.Item2 == null ? "无" : $"{tuple.Item2.TeamName},胜率:{tuple.Item2.WinningRatio}")}】");
            DisplayMessage($"    胜利战队【{winTeam.TeamName}】，失败战队【{failTeam.TeamName}】，模拟随机数【{randomNumber}】");
            UcTeam ucTeam = FindWinTeam(button, winTeam);
            if (ucTeam == null)
            {
                return;
            }

            Panel panel = new Panel();
            panel.Name = $"panel{button.Name.Substring(6)}";
            panel.Location = new Point(ucTeam.Location.X + 250, ucTeam.Location.Y + 10);
            panel.Size = new Size(100, 100);
            panel.BackgroundImage = null;
            Bitmap bitmap = new Bitmap(panel.Width, panel.Height);
            Graphics graphics = Graphics.FromImage(bitmap);
            graphics.DrawString("胜 利", new Font("华文楷体", 16), Brushes.Red, 10, 10);
            graphics.Dispose();
            panel.BackgroundImage = bitmap;
            panel1.Controls.Add(panel);
        }

        /// <summary>
        /// 获取两个比赛战队胜利一方对应的控件
        /// </summary>
        /// <param name="button"></param>
        /// <param name="winTeam"></param>
        /// <returns></returns>
        private UcTeam FindWinTeam(Button button, Team winTeam)
        {
            int index = int.Parse(button.Name.Substring(6)) - 1;
            Control[] controls = panel1.Controls.Find($"ucTeam{index * 2 + 1}", true);
            Control[] controls2 = panel1.Controls.Find($"ucTeam{index * 2 + 2}", true);
            if (controls != null && controls.Length > 0)
            {
                Team cTemp = ((UcTeam)controls[0]).Tag as Team;
                if (cTemp.TeamName == winTeam.TeamName)
                {
                    return (UcTeam)controls[0];
                }
                else
                {
                    if (controls2 != null && controls2.Length > 0)
                    {
                        cTemp = ((UcTeam)controls2[0]).Tag as Team;
                        if (cTemp.TeamName == winTeam.TeamName)
                        {
                            return (UcTeam)controls2[0];
                        }
                    }
                }
            }
            return null;
        }

        private void DisplayMessage(string message)
        {
            this.BeginInvoke(new Action(() =>
            {
                if (rtxtDisplay.TextLength >= 40960)
                {
                    rtxtDisplay.Clear();
                }
                rtxtDisplay.AppendText($"{DateTime.Now.ToString("HH:mm:ss")}-->{message}\n");
                rtxtDisplay.ScrollToCaret();
            }));
        }

        private void btnStart_MouseClick(object sender, MouseEventArgs e)
        {
            Team[] FinalTwoTeam = new Team[2];//最终决赛的两个战队，分出冠军、亚军
            do
            {
                WinTeamList.Clear();
                for (int i = 0; i < matchCount; i++)
                {
                    Button button = panel1.Controls.Find($"button{i + 1}", true)[0] as Button;
                    Button_Click(button, null);
                    Application.DoEvents();
                    Thread.Sleep(2000);
                }
                if (WinTeamList.Count == 1)
                {
                    //只有最后一个胜利战队，循环终止,找到亚军
                    Team secondPlace = Array.Find(FinalTwoTeam, c => c.TeamName != WinTeamList[0].TeamName);
                    DisplayMessage($"最终胜利战队,冠军【{WinTeamList[0].TeamName}】,亚军【{secondPlace.TeamName}】");
                    MessageBox.Show($"最终胜利战队,冠军【{WinTeamList[0].TeamName}】,亚军【{secondPlace.TeamName}】", "圆满结束");
                    break;
                }
                DisplayMessage($"当前胜利的战队为【{string.Join(",", WinTeamList.Select(Team => Team.TeamName))}】");
                Application.DoEvents();
                Thread.Sleep(3000);
                if (WinTeamList.Count == 2)
                {
                    WinTeamList.CopyTo(FinalTwoTeam);
                    string TeamBattle = $"决战即将开始,最终决赛双方：【{WinTeamList[0].TeamName} VS {WinTeamList[1].TeamName}】";
                    DisplayMessage(TeamBattle);
                    Application.DoEvents();
                    Thread.Sleep(1000);
                    MessageBox.Show(TeamBattle, "决战");
                }
                LoadMatchTeam(WinTeamList);
            } while (WinTeamList.Count >= 2);
        }

        private void btnRefresh_Click_1(object sender, EventArgs e)
        {
            rtxtDisplay.Clear();
            WinTeamList.Clear();
            FormTeam_Load(null, null);
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {

        }
    }
}
